# data_loader.py - 修复版本
import pandas as pd
import numpy as np
from datetime import datetime
import os


class DataLoader:
    def __init__(self, file_path):
        self.file_path = file_path
        self.df = None

    def load_data(self):
        """加载Excel数据文件"""
        try:
            print(f"正在加载数据文件: {self.file_path}")
            self.df = pd.read_excel(self.file_path)
            print(f"原始数据维度: {self.df.shape}")
            print("数据字段:", self.df.columns.tolist())
            return True
        except Exception as e:
            print(f"数据加载失败: {e}")
            return False

    def preprocess_data(self):
        """数据预处理"""
        if self.df is None:
            print("请先加载数据")
            return False

        print("\n=== 数据预处理 ===")

        # 检查缺失值
        self._check_missing_values()

        # 处理日期字段
        self._process_dates()

        # 处理异常值
        self._handle_outliers()

        # 处理使用状态
        self._process_coupon_status()

        # 计算衍生字段
        self._create_derived_features()

        print(f"预处理后数据维度: {self.df.shape}")
        return True

    def _check_missing_values(self):
        """检查缺失值"""
        missing_data = self.df.isnull().sum()
        missing_columns = missing_data[missing_data > 0]

        if len(missing_columns) > 0:
            print("缺失值统计:")
            for col, count in missing_columns.items():
                print(f"  {col}: {count}个缺失值 ({count / len(self.df):.2%})")
        else:
            print("无缺失值")

    def _process_dates(self):
        """处理日期字段 - 根据实际数据格式修复"""
        if '付款日期' in self.df.columns:
            print("处理付款日期字段...")

            # 检查当前类型和前几个值
            print(f"付款日期数据类型: {self.df['付款日期'].dtype}")
            print(f"付款日期前5个值:")
            print(self.df['付款日期'].head())

            try:
                # 直接转换为datetime
                self.df['付款日期'] = pd.to_datetime(self.df['付款日期'], errors='coerce')

                # 检查转换结果
                successful_conversions = self.df['付款日期'].notna().sum()
                failed_conversions = self.df['付款日期'].isna().sum()

                print(f"成功转换日期: {successful_conversions}/{len(self.df)}")
                if failed_conversions > 0:
                    print(f"转换失败的日期数量: {failed_conversions}")
                    # 显示转换失败的行
                    failed_rows = self.df[self.df['付款日期'].isna()]
                    print("转换失败的前5行:")
                    print(failed_rows.head()[['订单ID', '付款日期']])

            except Exception as e:
                print(f"日期格式转换失败: {e}")

    def _handle_outliers(self):
        """处理异常值 - 根据实际数据修复"""
        initial_count = len(self.df)

        # 处理实付金额异常值
        if '实付金额' in self.df.columns:
            # 记录负值数量
            negative_count = len(self.df[self.df['实付金额'] < 0])
            if negative_count > 0:
                print(f"发现负支付金额: {negative_count} 条")
                # 显示负值记录
                negative_records = self.df[self.df['实付金额'] < 0]
                print("负支付金额记录:")
                print(negative_records[['订单ID', '用户ID', '实付金额']])

            # 移除极端异常值（99.9%分位数以上）
            upper_limit = self.df['实付金额'].quantile(0.999)
            extreme_outliers = len(self.df[self.df['实付金额'] > upper_limit])

            if extreme_outliers > 0:
                print(f"移除极端异常值: {extreme_outliers} 条")
                self.df = self.df[self.df['实付金额'] <= upper_limit]

        # 处理购买数量异常值
        if '购买数量' in self.df.columns:
            # 移除负值或零值
            invalid_quantity = len(self.df[self.df['购买数量'] <= 0])
            if invalid_quantity > 0:
                print(f"移除无效购买数量: {invalid_quantity} 条")
                self.df = self.df[self.df['购买数量'] > 0]

        removed_count = initial_count - len(self.df)
        if removed_count > 0:
            print(f"总共移除异常记录: {removed_count} 条")

    def _process_coupon_status(self):
        """处理优惠券使用状态 - 根据实际数据修复"""
        if '使用状态' in self.df.columns:
            # 检查使用状态的唯一值
            unique_status = self.df['使用状态'].unique()
            print(f"使用状态唯一值: {sorted(unique_status)}")

            # 统计各状态数量
            status_counts = self.df['使用状态'].value_counts().sort_index()
            print("使用状态分布:")
            for status, count in status_counts.items():
                status_desc = "已使用" if status == 1 else "未使用" if status == 0 else f"未知状态({status})"
                print(f"  状态{status}({status_desc}): {count}条")

    def _create_derived_features(self):
        """创建衍生特征"""
        if '实付金额' in self.df.columns and '邮费' in self.df.columns:
            self.df['总金额'] = self.df['实付金额'] + self.df['邮费']
            print("已创建总金额字段")

    def get_data_info(self):
        """获取数据基本信息"""
        if self.df is not None:
            print("\n=== 数据基本信息 ===")
            print(f"数据形状: {self.df.shape}")

            print("\n=== 数值字段描述统计 ===")
            numeric_cols = self.df.select_dtypes(include=[np.number]).columns
            if len(numeric_cols) > 0:
                print(self.df[numeric_cols].describe())
            else:
                print("无数值字段")

            # 分类字段统计
            categorical_cols = self.df.select_dtypes(include=['object']).columns
            for col in categorical_cols:
                if col in self.df.columns:
                    print(f"\n{col} 唯一值数量: {self.df[col].nunique()}")
                    if self.df[col].nunique() <= 20:  # 只显示值较少的字段
                        print(f"{col} 值分布:")
                        print(self.df[col].value_counts().head(10))

    def get_clean_data(self):
        """获取清洗后的数据"""
        return self.df.copy()